#pragma once

#include "GameLogicBase.h"

#include "..\Resources\ResourceCache.h"

class TestudinApplicationBase
{
	// Protected Variables

	protected:

		HINSTANCE _hInstance;					// the module instance
		bool _bWindowedMode;					// true if the app is windowed, false if fullscreen
		bool _bIsRunning;						// true if everything is initialized and the game is in the main loop
		bool _bQuitRequested;					// true if the app should run the exit sequence
		bool _bQuitting;						// true if the app is running the exit sequence
		Rect _rcDesktop;						// current desktop size - not necessarilly the client window size
		Point _screenSize;					// game screen size
		int _iColorDepth;						// current color depth (16 or 32)
		GameLogicBase *_pGame;

	// Protected Methods

	protected:

		inline bool CheckStorage(const DWORDLONG diskSpaceNeeded);

		inline DWORD ReadCPUSpeed();

	// Inline Public Methods

	public:

		const Point &GetScreenSize()  { return _screenSize; }

		HINSTANCE GetInstance() { return _hInstance; }

	// Constructors

	public:

		TestudinApplicationBase();

	// Win32

	public:

		HWND GetHwnd();

		virtual bool InitInstance(
			HINSTANCE hInstance, 
			LPWSTR lpCmdLine, 
			HWND hWnd = NULL, 
			int screenWidth = SCREEN_WIDTH, 
			int screenHeight = SCREEN_HEIGHT);	

		static LRESULT CALLBACK MsgProc( 
			HWND hWnd, 
			UINT uMsg, 
			WPARAM wParam, 
			LPARAM lParam, 
			bool* pbNoFurtherProcessing, 
			void *pUserContext );

	// DirectX 11

	public:
		
		static bool CALLBACK IsD3D11DeviceAcceptable( 
			const CD3D11EnumAdapterInfo *AdapterInfo, 
			UINT Output, 
			const CD3D11EnumDeviceInfo *DeviceInfo, 
			DXGI_FORMAT BackBufferFormat, 
			bool bWindowed, 
			void* pUserContext );
		
		static HRESULT CALLBACK OnD3D11CreateDevice( 
			ID3D11Device* pd3dDevice, 
			const DXGI_SURFACE_DESC* pBackBufferSurfaceDesc, 
			void* pUserContext );
		
		static HRESULT CALLBACK OnD3D11ResizedSwapChain( 
			ID3D11Device* pd3dDevice, 
			IDXGISwapChain* pSwapChain, 
			const DXGI_SURFACE_DESC* pBackBufferSurfaceDesc, 
			void* pUserContext );
		
		static void CALLBACK OnD3D11ReleasingSwapChain( void* pUserContext );
		
		static void CALLBACK OnD3D11DestroyDevice( void* pUserContext );
		
		static void CALLBACK OnD3D11FrameRender( 
			ID3D11Device* pd3dDevice, 
			ID3D11DeviceContext* pd3dImmediateContext, 
			double fTime, 
			float fElapsedTime, 
			void* pUserContext );

		static bool CALLBACK ModifyDeviceSettings( 
			DXUTDeviceSettings* pDeviceSettings, 
			void* pUserContext );

		static void CALLBACK OnUpdateGame( 
			double fTime, 
			float fElapsedTime, 
			void *pUserContext );

	// Game

	public:
		
		virtual TCHAR *GetGameTitle() = 0;
		virtual TCHAR *GetGameAppDirectory() = 0;
		virtual HICON GetIcon() = 0;

		// You must define these functions to initialize your game.
		// Look for them in TeapotWars.h and TeapotWars.cpp
		virtual GameLogicBase *CreateGameAndView()=0;
		
		virtual bool LoadGame();

		ResourceCache *pResourceCache;

		GameLogicBase *GetGameLogic(void) const { return _pGame; }

	protected:
		
		virtual void RegisterGameEvents() {}

	private:
		
		void RegisterEngineEvents();
};

extern TestudinApplicationBase* globalApplicationPointer;